#include "RenderSystem.h"
#include "GraphicComponents.h"
#include "PositionComponent.h"
#include "Base/Exceptions.h"
#include "Base/Logger.h"
#include "Base/BPL.h"
#include <boost/lexical_cast.hpp>
#include <string>

RenderSystem::RenderSystem()
{
	
}
void RenderSystem::update(float dt)
{
    Assert(mpt_app != NULL);
	
	//hudLayer.setView(mpt_app->getView());
	firstLayer.setView(mpt_app->getView());
	secondLayer.setView(mpt_app->getView());
	thirdLayer.setView(mpt_app->getView());

	hudLayer.clear(sf::Color(0,0,0,0));
	firstLayer.clear(sf::Color(0,0,0,0));
	secondLayer.clear(sf::Color(0,0,0,0));
	thirdLayer.clear(sf::Color(0,0,0,0));

	sf::Vector2f posCenter = mpt_app->getView().getCenter();
	int sizeTile = entityManager->sizeTile;

	// METTRE UN RAYON DE NEIGHBOURHOOD
	std::deque<int> dynamicEntities = entityManager->getGrid()->getNeighbourhoodAt(0,posCenter);


    for(std::deque<int>::iterator itr = dynamicEntities.begin(); itr!=dynamicEntities.end(); )
    {
		if(entityManager->hasEntity((*itr)))
		{
			if(mpt_entitiesID.find(*itr)!=mpt_entitiesID.end())
			{
				GraphicComponentPtr graphEnt = entityManager->getEntity(*itr)->getAs<GraphicComponent>();
				if(graphEnt->imageType == GraphicComponent::NORMAL)
				{
					// FAIRE AVEC LE TRANSFORMABLE
					graphEnt->m_transform.setPosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);
					if(graphEnt->layer == GraphicComponent::FIRST)
						firstLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					else if(graphEnt->layer == GraphicComponent::SECOND)
						secondLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					else if(graphEnt->layer == GraphicComponent::THIRD)
						thirdLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					
					//mpt_app->draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
				}
				else
				{
					//UPDATE DU MODEL (meme si statique)
					ModelGraphicComponentPtr modelPtr = boost::dynamic_pointer_cast<ModelGraphicComponent>(graphEnt);
					modelPtr->model.update();
					modelPtr->model.setSpritePosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);
					
					if(graphEnt->layer == GraphicComponent::FIRST)
						firstLayer.draw(modelPtr->model.getCurrentSprite());
					else if(graphEnt->layer == GraphicComponent::SECOND)
						secondLayer.draw(modelPtr->model.getCurrentSprite());
					else if(graphEnt->layer == GraphicComponent::THIRD)
						thirdLayer.draw(modelPtr->model.getCurrentSprite());

					//mpt_app->draw(modelPtr->model.getCurrentSprite());
				}
			}
			itr++;
		}
		else
		{
			std::string str = "BUG RENDER : ";
			str += boost::lexical_cast<std::string>(*itr);
			BPL::Logger::log(str.c_str());
			itr = dynamicEntities.erase(itr);
		}
    }

	sf::Vector2i posCenteri(posCenter.x/sizeTile, posCenter.y/sizeTile);
	std::vector<int> staticEntities = entityManager->getMap()->getNeighbourhoodAt(posCenteri,15,15);
	
	for(std::vector<int>::iterator itr = staticEntities.begin(); itr!=staticEntities.end(); )
    {
		if(entityManager->hasEntity((*itr)))
		{
			if(mpt_entitiesID.find(*itr)!=mpt_entitiesID.end())
			{
				GraphicComponentPtr graphEnt = entityManager->getEntity(*itr)->getAs<GraphicComponent>();
				if(graphEnt->imageType == GraphicComponent::NORMAL)
				{
					// TRANSFORMABLE
					graphEnt->m_transform.setPosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);
					
					if(graphEnt->layer == GraphicComponent::FIRST)
						firstLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					else if(graphEnt->layer == GraphicComponent::SECOND)
						secondLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					else if(graphEnt->layer == GraphicComponent::THIRD)
						thirdLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
					//mpt_app->draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
				}
				else
				{
					//UPDATE DU MODEL (meme si statique)
					ModelGraphicComponentPtr modelPtr = boost::dynamic_pointer_cast<ModelGraphicComponent>(graphEnt);
					modelPtr->model.update();
					modelPtr->model.setSpritePosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);

					if(graphEnt->layer == GraphicComponent::FIRST)
						firstLayer.draw(modelPtr->model.getCurrentSprite());
					else if(graphEnt->layer == GraphicComponent::SECOND)
						secondLayer.draw(modelPtr->model.getCurrentSprite());
					else if(graphEnt->layer == GraphicComponent::THIRD)
						thirdLayer.draw(modelPtr->model.getCurrentSprite());
					//mpt_app->draw(modelPtr->model.getCurrentSprite());
				}
			}
			itr++;
		}
		else
		{
			itr = staticEntities.erase(itr);
		}
    }

	for(std::vector<int>::iterator itr = mpt_hudEnt.begin(); itr!=mpt_hudEnt.end(); )
    {
		if(entityManager->hasEntity((*itr)))
		{
			if(mpt_entitiesID.find(*itr)!=mpt_entitiesID.end())
			{
				GraphicComponentPtr graphEnt = entityManager->getEntity(*itr)->getAs<GraphicComponent>();
				if(graphEnt->imageType == GraphicComponent::NORMAL)
				{
					// TRANSFORMABLE
					graphEnt->m_transform.setPosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);
					
					hudLayer.draw(*graphEnt->m_sprite, graphEnt->m_transform.getTransform());
				}
				else if(graphEnt->imageType == GraphicComponent::MODEL)
				{
					//UPDATE DU MODEL (meme si statique)
					ModelGraphicComponentPtr modelPtr = boost::dynamic_pointer_cast<ModelGraphicComponent>(graphEnt);
					modelPtr->model.update();
					modelPtr->model.setSpritePosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);

					hudLayer.draw(modelPtr->model.getCurrentSprite());

				}
				else
				{
					TextGraphicComponentPtr textPtr = boost::dynamic_pointer_cast<TextGraphicComponent>(graphEnt);
					textPtr->text.setPosition(entityManager->getEntity(*itr)->getAs<PositionComponent>()->m_position);

					hudLayer.draw(textPtr->text);
				}
			}
			itr++;
		}
		else
		{
			itr = staticEntities.erase(itr);
		}
    }
	
	hudLayer.display();
	firstLayer.display();
	secondLayer.display();
	thirdLayer.display();
	
	mpt_app->clear(sf::Color(0,0,0,0));

	sf::Sprite hudLayer(hudLayer.getTexture());
	hudLayer.setPosition(posCenter - sf::Vector2f(mpt_app->getSize().x/2, mpt_app->getSize().y/2));
	sf::Sprite firstLayer(firstLayer.getTexture());
	firstLayer.setPosition(posCenter - sf::Vector2f(mpt_app->getSize().x/2, mpt_app->getSize().y/2));
	sf::Sprite secondLayer(secondLayer.getTexture());
	secondLayer.setPosition(posCenter - sf::Vector2f(mpt_app->getSize().x/2, mpt_app->getSize().y/2));
	sf::Sprite thirdLayer(thirdLayer.getTexture());
	thirdLayer.setPosition(posCenter - sf::Vector2f(mpt_app->getSize().x/2, mpt_app->getSize().y/2));

	mpt_app->draw(thirdLayer);
	mpt_app->draw(secondLayer);
	mpt_app->draw(firstLayer);
	mpt_app->draw(hudLayer);

    mpt_app->display();
}

void RenderSystem::addEntity(int ent)
{
	if(!entityManager->hasEntity(ent))
		return;

	GraphicComponentPtr graphEnt = entityManager->getEntity(ent)->getAs<GraphicComponent>();
	
	if(graphEnt->layer == GraphicComponent::HUD)
		mpt_hudEnt.push_back(ent);

    mpt_entitiesID.insert(ent);
	entityManager->getEntity(ent)->addSystem(this);
}

void RenderSystem::attachApp(sf::RenderWindow* app)
{
    mpt_app = app;
    Assert(mpt_app != NULL);

	hudLayer.create(mpt_app->getSize().x,mpt_app->getSize().y);
	firstLayer.create(mpt_app->getSize().x,mpt_app->getSize().y);
	secondLayer.create(mpt_app->getSize().x,mpt_app->getSize().y);
	thirdLayer.create(mpt_app->getSize().x,mpt_app->getSize().y);
}
